package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.boot.request.PageParams;
import com.eastfair.common.dto.CommonServiceBookingDTO;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.base.entity.SuperEntity;
import com.eastfair.core.exception.BizException;
import com.eastfair.home.api.HomeHomeServiceOrderFeign;
import com.eastfair.home.dto.ReportSpaceAuditDTO;
import com.eastfair.projectcore.enumeration.DataIsolationSystemSceneEnum;
import com.eastfair.projectcore.enumeration.MenuAffiliationEnum;
import com.eastfair.venueservice.dto.ExhibitionSettlementDTO;
import com.eastfair.venueservice.dto.ServiceBookingDTO;
import com.eastfair.venueservice.dto.ServiceBookingQuery;
import com.eastfair.venueservice.dto.ServiceOrderDTO;
import com.eastfair.venueservice.entity.*;
import com.eastfair.venueservice.enumeration.*;
import com.eastfair.venueservice.exceptioncode.VenueServiceExceptionCode;
import com.eastfair.venueservice.service.*;
import com.eastfair.venueservice.vo.ExhibitionSettlementVO;
import com.eastfair.venueservice.vo.ServiceBookingVO;
import com.eastfair.venueservice.vo.ServiceOrderVO;
import com.eastfair.venueservice.vo.ServiceProviderVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 主场，搭建商 的服务订单 Service.
 *
 * @author dqq
 * @date 2022 /11/10
 */
@Service
@Slf4j
public class HomeServiceOrderServiceImpl implements HomeServiceOrderService {

    /**
     * 是管理费
     */
    private static final int IS_MANAGE = 1;

    /**
     * 非管理费
     */
    private static final int IS_NOT_MANAGE = 0;

    @Resource
    private ServiceOrderService serviceOrderService;

    @Resource
    private ServiceBookingService serviceBookingService;

    @Resource
    private ServiceProviderService serviceProviderService;

    @Resource
    private ServiceCategoryService serviceCategoryService;

    @Resource
    private ServiceProviderSpaceService serviceProviderSpaceService;

    @Resource
    private ServiceOrderOperateLogService serviceOrderOperateLogService;

    @Resource
    private ExhibitionServiceProviderService exhibitionServiceProviderService;

    @Resource
    private VenueManageTransactionOrderService venueManageTransactionOrderService;

    @Resource
    private HomeHomeServiceOrderFeign homeHomeServiceOrderFeign;

    @Resource
    private ExhibitionCompanyService exhibitionCompanyService;

    @Resource(name = "threadPoolTaskExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Override
    public Page<ServiceOrderVO> listServiceOrderVOs(PageParams<ServiceOrderDTO> pageParams) {
        ServiceOrderDTO model = pageParams.getModel();
        if (model.getHomeId() != null && model.getExhibitionManageId() != null) {
            // 查询主场在展会中负责的展厅
            List<String> spaceCodeList = serviceProviderSpaceService.querySpaceCodeListByExhibitionId(model.getExhibitionManageId(), model.getHomeId());
            model.setSpaceCodeList(spaceCodeList);
        }
        return serviceOrderService.listServiceOrderVOs(pageParams);
    }

    @Override
    public List<ServiceOrderVO> listManageVOByExhibitorIdList(List<Long> exhibitorIdList) {
        ServiceOrderDTO query = new ServiceOrderDTO();
        query.setExhibitorIdList(exhibitorIdList);
        query.setIsManageExpense(BusinessConstant.YES);
        List<ServiceOrder> list = serviceOrderService.listServiceOrders(query);
        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }
        return list
                .stream()
                .map(serviceOrder -> BeanUtil.toBean(serviceOrder, ServiceOrderVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public List<ServiceOrderVO> listOrderVOByExhibitorId(Long exhibitorId) {
        ServiceOrderDTO query = new ServiceOrderDTO();
        query.setExhibitorId(exhibitorId);
        List<ServiceOrder> list = serviceOrderService.listServiceOrders(query);
        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }
        return list
                .stream()
                .map(serviceOrder -> BeanUtil.toBean(serviceOrder, ServiceOrderVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public List<ServiceOrderVO> listForHomeServiceOrderSettlement(ServiceOrderDTO query) {
        log.info("listForHomeServiceOrderSettlement - 查询需结算的主场服务订单与管理费订单, query={}", query);
        QueryWrapper<ServiceOrder> queryWrapper = createHomeSettlementQueryWrapper(query);
        List<ServiceOrder> serviceOrderList = serviceOrderService.list(queryWrapper);
        if (serviceOrderList == null || serviceOrderList.isEmpty()) {
            return Collections.emptyList();
        }
        return serviceOrderService.packageServiceBookingList(serviceOrderList);
    }

    @Override
    public List<ServiceOrderVO> listForVenueServiceOrderSettlement(ServiceOrderDTO query) {
        log.info("listForHomeServiceOrderSettlement - 查询需结算的综合服务订单, query={}", query);
        QueryWrapper<ServiceOrder> queryWrapper = createVenueSettlementQueryWrapper(query);
        List<ServiceOrder> serviceOrderList = serviceOrderService.list(queryWrapper);
        if (serviceOrderList == null || serviceOrderList.isEmpty()) {
            return Collections.emptyList();
        }
        return serviceOrderService.packageServiceBookingList(serviceOrderList);
    }

    @Override
    public ExhibitionSettlementVO getHomeServiceOrderSettlement(ExhibitionSettlementDTO query) {
        ServiceOrderDTO orderQuery = new ServiceOrderDTO();
        orderQuery.setExhibitionManageId(query.getExhibitionManageId());
        orderQuery.setCompanyId(query.getCompanyId());
        orderQuery.setSpaceCode(query.getSpaceCode());
        orderQuery.setSpaceName(query.getSpaceName());
        orderQuery.setSiteName(query.getSiteName());
        List<ServiceOrderVO> serviceOrderList = listForHomeServiceOrderSettlement(orderQuery);
        if (serviceOrderList == null || serviceOrderList.isEmpty()) {
            return null;
        }
        ExhibitionSettlementVO exhibitionSettlementVO = ServiceOrderService.calculateExhibitionSettlement(serviceOrderList);
        return exhibitionSettlementVO;
    }
    @Override
    public ExhibitionSettlementVO getVenueServiceOrderSettlement(ExhibitionSettlementDTO query) {
        ServiceOrderDTO orderQuery = new ServiceOrderDTO();
        Long companyId = query.getCompanyId();
        ServiceProvider serviceProvider = serviceProviderService.getById(companyId);
        if(Objects.nonNull(serviceProvider)){
            orderQuery.setCompanyCode(serviceProvider.getCompanyCode());
        }else {
            ExhibitionCompany exhibitionCompany = exhibitionCompanyService.getById(companyId);
            if(Objects.nonNull(exhibitionCompany)){
                orderQuery.setCompanyCode(exhibitionCompany.getCompanyCode());
            }
        }
        orderQuery.setExhibitionManageId(query.getExhibitionManageId());
        List<ServiceOrderVO> serviceOrderList = listForVenueServiceOrderSettlement(orderQuery);
        if (serviceOrderList == null || serviceOrderList.isEmpty()) {
            return null;
        }
        ExhibitionSettlementVO exhibitionSettlementVO = ServiceOrderService.calculateExhibitionSettlement(serviceOrderList);
        return exhibitionSettlementVO;
    }

    @Override
    public List<ServiceOrder> listManageOrderByExhibitorId(Long exhibitorId) {
        ServiceOrderDTO query = new ServiceOrderDTO();
        query.setExhibitorId(exhibitorId);
        query.setIsManageExpense(BusinessConstant.YES);
        return serviceOrderService.listServiceOrders(query);
    }

    @Override
    public boolean checkSiteManageOrderUnique(ServiceOrderDTO query) {
        // 展商ID为空，则无需校验
        if (query.getExhibitorId() == null) {
            return true;
        }
        List<ServiceOrder> list = listManageOrderByExhibitorId(query.getExhibitorId());
        if (list == null || list.isEmpty()) {
            return true;
        }
        boolean isUnique = true;
        for (ServiceOrder manageOrder : list) {
            if (manageOrder.getOrderStatus() != null && !ServiceOrderOrderStatusEnum.CANCEL.eq(manageOrder.getOrderStatus())) {
                isUnique = false;
                break;
            }
        }
        return isUnique;
    }

    @Override
    public ServiceOrderVO getVOByOrderNumber(String orderNumber) {
        return serviceOrderService.getVOByOrderNumber(orderNumber);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceOrder saveServiceOrderForBuilder(ServiceOrderDTO serviceOrderDTO) {
        List<CommonServiceBookingDTO> commonServiceBookingList = serviceOrderDTO.getCommonServiceBookingList();
        // 过滤保留非管理费服务
        List<Long> serviceCategoryIds = commonServiceBookingList
                .stream()
                .map(CommonServiceBookingDTO::getServiceCategoryId)
                .collect(Collectors.toList());
        List<CommonServiceBookingDTO> nonManageExpenseCommonServiceBookingList = filterService(serviceCategoryIds, IS_NOT_MANAGE, commonServiceBookingList);
        // 未预定非管理费服务，不生成服务订单
        if (nonManageExpenseCommonServiceBookingList == null || nonManageExpenseCommonServiceBookingList.isEmpty()) {
            return null;
        }
        // 计算订单金额，和每项服务的金额
        ServiceOrderService.calculateOrderAmount(serviceOrderDTO, nonManageExpenseCommonServiceBookingList);
        // 保存订单
        ServiceOrder serviceOrder = serviceOrderService.saveServiceOrder(serviceOrderDTO);
        String orderNumber = serviceOrder.getOrderNumber();
        // 处理预定服务
        List<ServiceBookingDTO> serviceBookingList = serviceOrderDTO.getServiceBookingList();
        for (ServiceBookingDTO serviceBookingDTO : serviceBookingList) {
            serviceBookingDTO.setOrderNumber(orderNumber);
            serviceBookingDTO.setBusinessId(serviceOrderDTO.getBuilderId());
            serviceBookingDTO.setExhibitorId(serviceOrderDTO.getExhibitorId());
            serviceBookingDTO.setExhibitorName(serviceOrderDTO.getExhibitorName());
            serviceBookingDTO.setDeclarationSystem(serviceOrderDTO.getBelongSystem());
            serviceBookingDTO.setProviderSystem(DataIsolationSystemSceneEnum.P_COMPOSITE_COURT.getCode());
        }
        // 批量保存服务预定
        serviceBookingService.addServiceBookingOfOrder(serviceBookingList);
        return serviceOrder;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceOrder saveManageExpenseOrderForBuilder(ServiceOrderDTO serviceOrderDTO) {
        List<CommonServiceBookingDTO> commonServiceBookingList = serviceOrderDTO.getCommonServiceBookingList();
        // 过滤保留管理费服务
        List<Long> serviceCategoryIds = commonServiceBookingList
                .stream()
                .map(CommonServiceBookingDTO::getServiceCategoryId)
                .collect(Collectors.toList());
        List<CommonServiceBookingDTO> manageExpenseCommonServiceBookingList = filterService(serviceCategoryIds, IS_MANAGE, commonServiceBookingList);
        // 未预定管理费服务，不生成管理费订单
        if (manageExpenseCommonServiceBookingList == null || manageExpenseCommonServiceBookingList.isEmpty()) {
            return null;
        }
        // 计算订单金额，和每项服务的金额
        ServiceOrderService.calculateOrderAmount(serviceOrderDTO, manageExpenseCommonServiceBookingList);
        // 是管理费订单
        serviceOrderDTO.setIsManageExpense(IS_MANAGE);
        // 展位管理费唯一性校验
        if (!checkSiteManageOrderUnique(serviceOrderDTO)) {
            throw BizException.wrap(VenueServiceExceptionCode.MANAGE_ORDER_HAS_EXIST.getCode(), "该展位已存在管理费订单");
        }
        // 保存订单
        ServiceOrder serviceOrder = serviceOrderService.saveServiceOrder(serviceOrderDTO);
        String orderNumber = serviceOrder.getOrderNumber();
        // 更新服务项的订单号
        List<ServiceBookingDTO> serviceBookingList = serviceOrderDTO.getServiceBookingList();
        for (ServiceBookingDTO serviceBookingDTO : serviceBookingList) {
            serviceBookingDTO.setOrderNumber(orderNumber);
            serviceBookingDTO.setBusinessId(serviceOrderDTO.getBuilderId());
            serviceBookingDTO.setExhibitorId(serviceOrderDTO.getExhibitorId());
            serviceBookingDTO.setExhibitorName(serviceOrderDTO.getExhibitorName());
            serviceBookingDTO.setDeclarationSystem(serviceOrderDTO.getBelongSystem());
            serviceBookingDTO.setProviderSystem(DataIsolationSystemSceneEnum.P_COMPOSITE_COURT.getCode());
        }
        // 批量保存服务预定
        serviceBookingService.addServiceBookingOfOrder(serviceBookingList);
        return serviceOrder;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ServiceOrder> saveOrderForBuilder(ServiceOrderDTO serviceOrderDTO) {
        log.info("saveOrderForBuilder - 保存搭建商服务订单与管理费订单, serviceOrderDTO={}", serviceOrderDTO);
        List<CommonServiceBookingDTO> commonServiceBookingList = serviceOrderDTO.getCommonServiceBookingList();
        if (commonServiceBookingList == null || commonServiceBookingList.isEmpty()) {
            throw BizException.wrap(VenueServiceExceptionCode.ORDER_CAN_NOT_CREATE.getCode(), "无法生成订单，未预定服务");
        }
        List<ServiceOrder> orderList = new ArrayList<>(16);
        // 保存服务订单
        ServiceOrder serviceOrder = saveServiceOrderForBuilder(serviceOrderDTO);
        if (serviceOrder != null) {
            orderList.add(serviceOrder);
        }
        // 保存管理费订单
        ServiceOrder expenseOrder = saveManageExpenseOrderForBuilder(serviceOrderDTO);
        if (expenseOrder != null) {
            orderList.add(expenseOrder);
        }
        return orderList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceOrder saveServiceOrderByReportSpaceAudit(ReportSpaceAuditDTO reportSpaceAuditDTO) {
        log.info("saveServiceOrderByReportSpaceAudit - 主场报馆审核记录生成服务订单, reportSpaceAudit={}", reportSpaceAuditDTO);
        // 生成服务订单
        ServiceOrderDTO serviceOrderDTO = toServiceOrderDTO(reportSpaceAuditDTO);
        // 查询订单下非管理费服务
        List<ServiceBooking> serviceBookingList = serviceBookingService.getByReportSpaceNumber(reportSpaceAuditDTO.getReportSpaceId(), IS_NOT_MANAGE);
        // 没有非管理费服务报馆，不生成服务订单
        if (serviceBookingList == null || serviceBookingList.isEmpty()) {
            return null;
        }
        // 计算订单的总金额，和每项服务的金额
        List<ServiceBookingDTO> serviceBookingDTOList = serviceBookingList
                .stream()
                .map(serviceBooking -> BeanUtil.toBean(serviceBooking, ServiceBookingDTO.class))
                .collect(Collectors.toList());
        serviceOrderDTO.setServiceBookingList(serviceBookingDTOList);
        ServiceOrderService.calculateOrderAmount(serviceOrderDTO);
        // 保存服务订单
        ServiceOrder serviceOrder = serviceOrderService.saveServiceOrder(serviceOrderDTO);
        // 服务预定列表更新订单号
        serviceBookingService.updateOrderNumber(serviceBookingList, serviceOrder.getOrderNumber());
        // 更新搭建商订单的报馆状态
        updateIsNeedReportVenue(serviceOrder.getOrderNumber());
        return serviceOrder;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceOrder saveManageExpenseOrderByReportSpaceAudit(ReportSpaceAuditDTO reportSpaceAuditDTO) {
        log.info("saveManageExpenseOrderByReportSpaceAudit - 主场报馆审核记录生成管理费订单, reportSpaceAudit={}", reportSpaceAuditDTO);
        // 生成管理费订单
        ServiceOrderDTO serviceOrderDTO = toServiceOrderDTO(reportSpaceAuditDTO);
        // 是管理费
        serviceOrderDTO.setIsManageExpense(IS_MANAGE);
        // 查询订单下的管理费服务
        List<ServiceBooking> serviceBookingList = serviceBookingService.getByReportSpaceNumber(reportSpaceAuditDTO.getReportSpaceId(), IS_MANAGE);
        // 没有管理费服务报馆，不生成管理费订单
        if (serviceBookingList == null || serviceBookingList.isEmpty()) {
            return null;
        }
        // 计算订单的总金额，和每项服务的金额
        List<ServiceBookingDTO> serviceBookingDTOList = serviceBookingList
                .stream()
                .map(serviceBooking -> BeanUtil.toBean(serviceBooking, ServiceBookingDTO.class))
                .collect(Collectors.toList());
        serviceOrderDTO.setServiceBookingList(serviceBookingDTOList);
        ServiceOrderService.calculateOrderAmount(serviceOrderDTO);
        // 展位管理费唯一性校验
        if (!checkSiteManageOrderUnique(serviceOrderDTO)) {
            throw BizException.wrap(VenueServiceExceptionCode.MANAGE_ORDER_HAS_EXIST.getCode(), "该展位已存在管理费订单");
        }
        // 保存管理费订单
        ServiceOrder serviceOrder = serviceOrderService.saveServiceOrder(serviceOrderDTO);
        // 服务预定列表更新订单号
        serviceBookingService.updateOrderNumber(serviceBookingList, serviceOrder.getOrderNumber());
        // 更新搭建商订单的报馆状态
        updateIsNeedReportVenue(serviceOrder.getOrderNumber());
        return serviceOrder;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ServiceOrder> saveOrderForReportSpace(ReportSpaceAuditDTO reportSpaceAuditDTO) {
        log.info("saveOrderForReportSpace - 主场报馆审核通过生成订单, reportSpaceAudit={}", reportSpaceAuditDTO);
        // 生成服务订单
        ServiceOrder serviceOrder = saveServiceOrderByReportSpaceAudit(reportSpaceAuditDTO);
        // 生成管理费订单
        ServiceOrder manageExpenseOrder = saveManageExpenseOrderByReportSpaceAudit(reportSpaceAuditDTO);
        List<ServiceOrder> list = new ArrayList<>();
        if (serviceOrder != null) {
            list.add(serviceOrder);
        }
        if (manageExpenseOrder != null) {
            list.add(manageExpenseOrder);
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceOrder updateServiceOrder(ServiceOrderDTO serviceOrderDTO) {
        return serviceOrderService.updateServiceOrder(serviceOrderDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitServiceOrder(String orderNumber) {
        // 更新订单状态为已提交
        serviceOrderService.submitServiceOrder(orderNumber);
        // 更新搭建商订单报馆状态
        updateIsNeedReportVenue(orderNumber);
        // 生成支付系统订单
        saveTransactionOrder(orderNumber);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitServiceOrder(List<String> orderNumberList) {
        log.info("submitServiceOrder - 批量提交订单, orderNumberList={}", orderNumberList);
        if (orderNumberList == null || orderNumberList.isEmpty()) {
            return false;
        }
        orderNumberList.forEach(this::submitServiceOrder);
        return true;
    }

    @Override
    public boolean saveTransactionOrder(String orderNumber) {
        ServiceOrder serviceOrder = serviceOrderService.getByOrderNumber(orderNumber);
        if (serviceOrder == null) {
            throw BizException.wrap(VenueServiceExceptionCode.ORDER_NOT_EXIST.getCode(), "订单不存在");
        }
        ServiceOrderDTO serviceOrderDTO = completeForTransactionOrder(serviceOrder);
        try {
            serviceOrderService.saveTransactionOrder(serviceOrderDTO);
        } catch (BizException e) {
            // 发送配置收款账号的站内信
            if (e.getCode() == VenueServiceExceptionCode.PAYEE_NOT_CONFIG.getCode()) {
                asyncSendConfigPayeeInnerMsg(serviceOrderDTO);
                return true;
            }
            throw e;
        }
        return true;
    }

    @Override
    public ServiceOrderDTO completeForTransactionOrder(ServiceOrder serviceOrder) {
        ServiceOrderDTO serviceOrderDTO = BeanUtil.toBean(serviceOrder, ServiceOrderDTO.class);
        serviceOrderDTO.setSystemCode(MenuAffiliationEnum.P_COMPOSITE_COURT.getCode());
        // 查询主场做为收款方
        ServiceProviderVO home = exhibitionServiceProviderService.getHomeByExhibitionIdAndSpaceCode(serviceOrderDTO.getExhibitionManageId(), serviceOrderDTO.getSpaceCode());
        if (home == null) {
            throw BizException.wrap(VenueServiceExceptionCode.PAYEE_NOT_EXIST.getCode(), "未找到负责该展厅的主场，无法生成订单");
        }
        serviceOrderDTO.setPayee(home.getCompanyName());
        return serviceOrderDTO;
    }

    @Override
    public boolean cancelServiceOrder(String orderNumber) {
        log.info("cancelServiceOrder - 取消订单, orderNumber={}", orderNumber);
        ServiceOrder serviceOrder = serviceOrderService.getByOrderNumber(orderNumber);
        if (serviceOrder == null) {
            throw BizException.wrap(VenueServiceExceptionCode.ORDER_NOT_EXIST.getCode(), "取消失败，订单不存在");
        }
        if (ServiceOrderOrderStatusEnum.PARTIAL_REPORT_VENUE.eq(serviceOrder.getOrderStatus())
                || ServiceOrderOrderStatusEnum.HAS_REPORT_VENUE.eq(serviceOrder.getOrderStatus())) {
            throw BizException.wrap(VenueServiceExceptionCode.ORDER_CAN_NOT_CANCEL.getCode(), "订单已报馆，不可取消");
        }
        if (ServiceOrderOrderStatusEnum.COMPLETE.eq(serviceOrder.getOrderStatus())
                && !ServiceOrderServiceReportVenueStatusEnum.NOT_NEED_REPORT.eq(serviceOrder.getServiceReportVenueStatus())) {
            throw BizException.wrap(VenueServiceExceptionCode.ORDER_CAN_NOT_CANCEL.getCode(), "订单已完成，不可取消");
        }
        // 发起退款申请
        if (ServiceOrderPayStatusEnum.HAS_PAY.eq(serviceOrder.getPayStatus()) || ServiceOrderPayStatusEnum.PARTIAL_PAY.eq(serviceOrder.getPayStatus())) {
            ServiceOrderDTO refundServiceOrderDTO = BeanUtil.toBean(serviceOrder, ServiceOrderDTO.class);
            applyServiceOrderRefund(refundServiceOrderDTO);
            // 如果订单已经支付，支付系统订单先不能取消，要等退款结束之后再取消，取消支付系统交易订单
        } else {
            // 取消支付系统订单
            venueManageTransactionOrderService.cancel(orderNumber);
        }
        // 更新订单状态为已取消
        updateOrderStatusCancel(orderNumber);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public boolean cancelTimeoutNotPayServiceOrder(String orderNumber) {
        return cancelServiceOrder(orderNumber);
    }

    @Override
    public ServiceOrder updateOrderStatusCancel(String orderNumber) {
        log.info("updateOrderStatusCancel - 更新订单状态为已取消, orderNumber={}", orderNumber);
        return transactionTemplate.execute(status -> {
            ServiceOrder serviceOrder = serviceOrderService.getByOrderNumber(orderNumber);
            if (serviceOrder == null) {
                throw BizException.wrap(VenueServiceExceptionCode.ORDER_NOT_EXIST.getCode(), "取消失败，订单不存在");
            }
            serviceOrder.setOrderStatus(ServiceOrderOrderStatusEnum.CANCEL);
            serviceOrderService.updateById(serviceOrder);
            // 记录操作日志
            serviceOrderOperateLogService.asyncLogCancelServiceOrder(serviceOrder);
            // 将订单下服务修改为已取消
            ServiceBookingDTO serviceBookingDTO = new ServiceBookingDTO();
            serviceBookingDTO.setOrderNumber(serviceOrder.getOrderNumber());
            serviceBookingDTO.setOrderStatus(ServiceBookingOrderStatusEnum.CANCEL);
            serviceBookingService.updateBookingServiceOrderStatus(serviceOrder, serviceBookingDTO);
            // 处理库存
            ServiceOrderDTO serviceOrderDTO = new ServiceOrderDTO();
            serviceOrderDTO.setOrderNumber(orderNumber);
            serviceOrderDTO.setOrderStatus(ServiceOrderOrderStatusEnum.CANCEL);
            serviceBookingService.updateServiceInventory(serviceOrderDTO);
            return serviceOrder;
        });
    }

    @Override
    public boolean applyServiceOrderRefund(ServiceOrderDTO serviceOrderDTO) {
        serviceOrderDTO.setSystemCode(MenuAffiliationEnum.P_COMPOSITE_COURT.getCode());
        return serviceOrderService.applyServiceOrderRefund(serviceOrderDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOrderStatusComplete(ServiceOrder serviceOrder) {
        log.info("updateOrderStatusComplete - 更新订单状态为已完成, serviceOrder={}", serviceOrder);
        if (ServiceOrderOrderStatusEnum.COMPLETE.eq(serviceOrder.getOrderStatus())) {
            return true;
        }
        // 订单未支付完成，订单不能完成
        if (!ServiceOrderPayStatusEnum.HAS_PAY.eq(serviceOrder.getPayStatus())) {
            return false;
        }
        // 如果订单不需要报馆，则更新订单状态为已完成
        if (ServiceOrderServiceReportVenueStatusEnum.NOT_NEED_REPORT.eq(serviceOrder.getServiceReportVenueStatus()) && ServiceOrderOrderStatusEnum.DISPATCH.eq(serviceOrder.getOrderStatus())) {
            return serviceOrderService.updateOrderStatusComplete(serviceOrder);
        }
        // 如果订单需要报馆并且已报馆，则更新订单状态为已完成
        if (ServiceOrderOrderStatusEnum.HAS_REPORT_VENUE.eq(serviceOrder.getOrderStatus())) {
            return serviceOrderService.updateOrderStatusComplete(serviceOrder);
        }
        return false;
    }

    @Override
    public boolean updateOrderStatusPartialReportVenue(String orderNumber) {
        log.info("updateOrderStatusPartialReportVenue - 更新搭建商订单状态为部分报馆, orderNumber={}", orderNumber);
        ServiceOrder serviceOrder = serviceOrderService.getByOrderNumber(orderNumber);
        if (serviceOrder == null) {
            throw BizException.wrap(VenueServiceExceptionCode.ORDER_NOT_EXIST.getCode(), "订单不存在");
        }
        if (ServiceOrderServiceReportVenueStatusEnum.NOT_NEED_REPORT.eq(serviceOrder.getServiceReportVenueStatus())) {
            return false;
        }
        if (ServiceOrderOrderStatusEnum.PARTIAL_REPORT_VENUE.eq(serviceOrder.getOrderStatus())) {
            return true;
        }
        if (ServiceOrderOrderStatusEnum.HAS_REPORT_VENUE.eq(serviceOrder.getOrderStatus())) {
            return true;
        }
        if (ServiceOrderOrderStatusEnum.COMPLETE.eq(serviceOrder.getOrderStatus())) {
            return true;
        }
        serviceOrder.setOrderStatus(ServiceOrderOrderStatusEnum.PARTIAL_REPORT_VENUE);
        return serviceOrderService.updateById(serviceOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOrderStatusHasReportVenue(String orderNumber) {
        log.info("updateOrderStatusHasReportVenue - 更新搭建商订单状态为已报馆, orderNumber={}", orderNumber);
        ServiceOrder serviceOrder = serviceOrderService.getByOrderNumber(orderNumber);
        if (serviceOrder == null) {
            throw BizException.wrap(VenueServiceExceptionCode.ORDER_NOT_EXIST.getCode(), "订单不存在");
        }
        if (ServiceOrderServiceReportVenueStatusEnum.NOT_NEED_REPORT.eq(serviceOrder.getServiceReportVenueStatus())) {
            return false;
        }
        if (ServiceOrderOrderStatusEnum.HAS_REPORT_VENUE.eq(serviceOrder.getOrderStatus())) {
            return true;
        }
        if (ServiceOrderOrderStatusEnum.COMPLETE.eq(serviceOrder.getOrderStatus())) {
            return true;
        }
        // 更新订单状态为已报馆
        serviceOrder.setOrderStatus(ServiceOrderOrderStatusEnum.HAS_REPORT_VENUE);
        serviceOrderService.updateById(serviceOrder);
        // 如果订单状态为已报馆，则尝试更新订单状态改为已完成
        return updateOrderStatusComplete(serviceOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateServiceReportVenueStatus(ServiceOrder serviceOrder) {
        log.info("updateServiceReportVenueStatus - 更新搭建商订单服务报馆状态, serviceOrder={}", serviceOrder);
        // 更新搭建商订单服务报馆状态
        UpdateWrapper<ServiceOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .eq(ServiceOrder::getIsDeleted, BusinessConstant.NO)
                .eq(ServiceOrder::getOrderNumber, serviceOrder.getOrderNumber())
                .set(ServiceOrder::getServiceReportVenueStatus, serviceOrder.getServiceReportVenueStatus());
        serviceOrderService.update(updateWrapper);
        // 更新搭建商订单状态为部分报馆
        if (ServiceOrderServiceReportVenueStatusEnum.PARTIAL_REPORT.eq(serviceOrder.getServiceReportVenueStatus())) {
            return updateOrderStatusPartialReportVenue(serviceOrder.getOrderNumber());
        }
        // 更新搭建商订单状态为已报馆
        if (ServiceOrderServiceReportVenueStatusEnum.HAS_REPORT.eq(serviceOrder.getServiceReportVenueStatus())) {
            return updateOrderStatusHasReportVenue(serviceOrder.getOrderNumber());
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateIsNeedReportVenue(String orderNumber) {
        log.info("updateIsNeedReportVenue - 更新搭建商订单是否需要报馆, orderNumber={}", orderNumber);
        ServiceOrder serviceOrder = serviceOrderService.getByOrderNumber(orderNumber);
        if (serviceOrder == null) {
            throw BizException.wrap(VenueServiceExceptionCode.ORDER_NOT_EXIST.getCode(), "订单不存在");
        }
        // 查询订单下预定的服务
        ServiceBookingQuery serviceBookingQuery = new ServiceBookingQuery();
        serviceBookingQuery.setExhibitionManageId(serviceOrder.getExhibitionManageId());
        serviceBookingQuery.setOrderNumber(orderNumber);
        List<ServiceBookingVO> serviceBookingList = serviceBookingService.queryServiceBookingListOfOrder(serviceBookingQuery);
        if (serviceBookingList == null || serviceBookingList.isEmpty()) {
            throw BizException.wrap(-1, "未预定服务");
        }
        // 预定服务列表中的服务是否存在场馆或配套商提供的服务，存在则需要报馆，不存在则不需要报馆
        boolean isNeedReportVenue = false;
        for (ServiceBookingVO serviceBookingVO : serviceBookingList) {
            boolean isVenueProvideService = MenuAffiliationEnum.P_COMPOSITE_VENUE.getCode().equals(serviceBookingVO.getSourceProvider())
                    || MenuAffiliationEnum.P_COMPOSITE_MATING.getCode().equals(serviceBookingVO.getSourceProvider());
            if (StrUtil.isNotBlank(serviceBookingVO.getSourceProvider()) && isVenueProvideService) {
                isNeedReportVenue = true;
                break;
            }
        }
        if (isNeedReportVenue) {
            // 需要报馆，将报馆状态值设置为未报馆
            serviceOrder.setServiceReportVenueStatus(ServiceOrderServiceReportVenueStatusEnum.NOT_REPORT);
            return serviceOrderService.updateById(serviceOrder);
        }
        // 不需要报馆，将报馆状态值设置为不需要报馆
        serviceOrder.setServiceReportVenueStatus(ServiceOrderServiceReportVenueStatusEnum.NOT_NEED_REPORT);
        serviceOrderService.updateById(serviceOrder);
        // 如果不需要报馆，则尝试更新订单为已完成
        return updateOrderStatusComplete(serviceOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean payServiceOrder(ServiceOrderDTO serviceOrderDTO) {
        log.info("payServiceOrder - 支付订单, serviceOrderDTO={}", serviceOrderDTO);
        ServiceOrder serviceOrder = serviceOrderService.updatePayStatus(serviceOrderDTO);
        if (!ServiceOrderPayStatusEnum.HAS_PAY.eq(serviceOrder.getPayStatus())) {
            return true;
        }
        // 全部支付完成，更新库存
        serviceOrderDTO.setPayStatus(serviceOrder.getPayStatus());
        // 全部支付完成，更新库存
        serviceBookingService.updateServiceInventory(serviceOrderDTO);
        // 如果订单支付完成，则尝试更新订单状态改为已完成
        return updateOrderStatusComplete(serviceOrder);
    }

    @Override
    public boolean sendConfigPayeeInnerMsg(ServiceOrderDTO serviceOrder) {
        log.info("sendConfigPayeeInnerMsg - 发送配置收款商户的站内信, serviceOrder={}", serviceOrder);
        R<Boolean> result = homeHomeServiceOrderFeign.sendConfigPayeeInnerMsg(serviceOrder);
        log.info("sendConfigPayeeInnerMsg - 发送配置收款商户的站内信完成, result={}", result);
        if(!result.getIsSuccess()) {
            throw BizException.wrap(result.getCode(), result.getMsg());
        }
        return result.getData();
    }

    @Override
    public void asyncSendConfigPayeeInnerMsg(ServiceOrderDTO serviceOrder) {
        log.info("asyncSendConfigPayeeInnerMsg - 异步发送配置收款商户的站内信, serviceOrder={}", serviceOrder);
        threadPoolTaskExecutor.execute(() -> sendConfigPayeeInnerMsg(serviceOrder));
    }

    /**
     * 过滤服务
     *
     * @param serviceCategoryIds       服务分类id
     * @param val                      0非管理费，1是管理费
     * @param commonServiceBookingList 服务列表
     * @return 服务列表
     */
    private List<CommonServiceBookingDTO> filterService(List<Long> serviceCategoryIds, int val, List<CommonServiceBookingDTO> commonServiceBookingList) {
        List<ServiceCategory> serviceCategoryList = serviceCategoryService
                .list(new QueryWrapper<ServiceCategory>()
                        .lambda()
                        .in(ServiceCategory::getId, serviceCategoryIds)
                        .eq(ServiceCategory::getIsManage, val));
        Map<Long, ServiceCategory> serviceCategoryMap = serviceCategoryList
                .stream()
                .collect(Collectors.toMap(SuperEntity::getId, Function.identity()));
        commonServiceBookingList = commonServiceBookingList
                .stream()
                .filter(e -> serviceCategoryMap.containsKey(e.getServiceCategoryId()))
                .collect(Collectors.toList());
        return commonServiceBookingList;
    }

    /**
     * 报馆审核记录生成 ServiceOrderDTO.
     *
     * @param reportSpaceAuditDTO the report space audit
     * @return the service order dto
     */
    private ServiceOrderDTO toServiceOrderDTO(ReportSpaceAuditDTO reportSpaceAuditDTO) {
        ServiceOrderDTO serviceOrderDTO = new ServiceOrderDTO();
        serviceOrderDTO.setOrderStatus(ServiceOrderOrderStatusEnum.SUBMIT);
        serviceOrderDTO.setOrderSource(ServiceOrderOrderSourceEnum.BUILDER_REPORT);
        serviceOrderDTO.setOrderTime(LocalDateTime.now());
        serviceOrderDTO.setExhibitionManageId(reportSpaceAuditDTO.getExhibitionId());
        serviceOrderDTO.setExhibitionManageName(reportSpaceAuditDTO.getExhibitionName());
        //  封装订单企业信息
        ServiceProvider serviceProvider = serviceProviderService.getById(reportSpaceAuditDTO.getBuilderId());
        if (serviceProvider == null) {
            throw BizException.wrap(VenueServiceExceptionCode.SERVICE_PROVIDER_NOT_EXIST);
        }
        serviceOrderDTO.setCompanyId(serviceProvider.getId());
        serviceOrderDTO.setCompanyCode(serviceProvider.getCompanyCode());
        serviceOrderDTO.setCompanyName(serviceProvider.getCompanyName());
        serviceOrderDTO.setCompanyType(serviceProvider.getServiceProviderType());
        serviceOrderDTO.setContact(serviceProvider.getPrincipalName());
        serviceOrderDTO.setPhone(serviceProvider.getPrincipalMobile());

        serviceOrderDTO.setExhibitorId(reportSpaceAuditDTO.getExhibitorId());
        serviceOrderDTO.setExhibitorName(reportSpaceAuditDTO.getExhibitorName());
        serviceOrderDTO.setSpaceCode(reportSpaceAuditDTO.getSpaceCode());
        serviceOrderDTO.setSpaceName(reportSpaceAuditDTO.getSpaceName());
        serviceOrderDTO.setSiteName(reportSpaceAuditDTO.getSiteName());
        serviceOrderDTO.setBelongSystem(DataIsolationSystemSceneEnum.P_COMPOSITE_PRODUCER.getCode());
        return serviceOrderDTO;
    }

    /**
     * 主场服务管理费订单待结算查询.
     *
     * @param query the query
     * @return the query wrapper
     */
    private static QueryWrapper<ServiceOrder> createHomeSettlementQueryWrapper(ServiceOrderDTO query) {
        QueryWrapper<ServiceOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ServiceOrder::getIsDeleted, BusinessConstant.DELETE_NO)
                .in(ServiceOrder::getBelongSystem, MenuAffiliationEnum.P_COMPOSITE_COURT.getCode(), MenuAffiliationEnum.P_COMPOSITE_PRODUCER.getCode())
                .in(ServiceOrder::getOrderSource, ServiceOrderOrderSourceEnum.ONLINE_BOOK, ServiceOrderOrderSourceEnum.BUILDER_REPORT,
                        ServiceOrderOrderSourceEnum.BUILDER_ONLINE_BOOK, ServiceOrderOrderSourceEnum.HOME_BUILDER_ORDER)
                .ne(ServiceOrder::getOrderStatus, ServiceOrderOrderStatusEnum.NOT_SUBMIT)
                .ne(ServiceOrder::getOrderStatus, ServiceOrderOrderStatusEnum.CANCEL)
                .eq(query.getExhibitionManageId() != null, ServiceOrder::getExhibitionManageId, query.getExhibitionManageId())
                .eq(query.getCompanyId() != null, ServiceOrder::getCompanyId, query.getCompanyId())
                .in(query.getCompanyIdList() != null && !query.getCompanyIdList().isEmpty(), ServiceOrder::getCompanyId, query.getCompanyIdList())
                .in(query.getSpaceCodeList() != null && !query.getSpaceCodeList().isEmpty(), ServiceOrder::getSpaceCode, query.getSpaceCodeList())
                .eq(StrUtil.isNotBlank(query.getSpaceCode()), ServiceOrder::getSpaceCode, query.getSpaceCode())
                .eq(StrUtil.isNotBlank(query.getSpaceName()), ServiceOrder::getSpaceName, query.getSpaceName())
                .eq(StrUtil.isNotBlank(query.getSiteName()), ServiceOrder::getSiteName, query.getSiteName())
        ;
        return queryWrapper;
    }

    /**
     * 综合服务订单待结算查询.
     *
     * @param query the query
     * @return the query wrapper
     */
    private static QueryWrapper<ServiceOrder> createVenueSettlementQueryWrapper(ServiceOrderDTO query) {
        QueryWrapper<ServiceOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ServiceOrder::getIsDeleted, BusinessConstant.DELETE_NO)
                .in(ServiceOrder::getBelongSystem, MenuAffiliationEnum.P_COMPOSITE_VENUE.getCode())
                .in(ServiceOrder::getOrderSource, ServiceOrderOrderSourceEnum.ON_SITE_ORDER)
                .ne(ServiceOrder::getOrderStatus, ServiceOrderOrderStatusEnum.NOT_SUBMIT)
                .ne(ServiceOrder::getOrderStatus, ServiceOrderOrderStatusEnum.CANCEL)
                .eq(query.getExhibitionManageId() != null, ServiceOrder::getExhibitionManageId, query.getExhibitionManageId())
                .eq(ServiceOrder::getCompanyCode, query.getCompanyCode())
        ;
        return queryWrapper;
    }
}